package Map中的流式编程;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class MapStreamExamples {

    public static void main(String[] args) {
        // 模拟生产环境数据
        Map<Integer, Employee> employeeMap = new HashMap<>();
        employeeMap.put(101, new Employee("张三", "技术部", 15000, 28));
        employeeMap.put(102, new Employee("李四", "市场部", 8500, 25));
        employeeMap.put(103, new Employee("王五", "技术部", 18000, 32));
        employeeMap.put(104, new Employee("赵六", "财务部", 9500, 35));
        employeeMap.put(105, new Employee("钱七", "市场部", 9200, 26));

        Map<String, Integer> productStock = Map.of(
            "iPhone13", 25,
            "MacBook Pro", 12,
            "AirPods Pro", 0,
            "iPad Air", 8,
            "Apple Watch", 0
        );

        Map<String, List<Order>> customerOrders = Map.of(
            "customer1@example.com", Arrays.asList(
                new Order("ORD-1001", 12999.0),
                new Order("ORD-1002", 8999.0)
            ),
            "customer2@example.com", Arrays.asList(
                new Order("ORD-2001", 14999.0)
            ),
            "customer3@example.com", Collections.emptyList()
        );

        // ===================================================================
        // 1. Map过滤：筛选高薪员工 (entrySet().stream().filter())
        // 场景：薪酬分析系统
        // ===================================================================
        Map<Integer, Employee> highSalaryEmployees = employeeMap.entrySet().stream()
            .filter(entry -> entry.getValue().getSalary() > 10000)
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue
            ));
        System.out.println("==== 高薪员工 ====\n" + highSalaryEmployees);

        // ===================================================================
        // 2. Map转换：获取所有部门名称 (values().stream().map())
        // 场景：组织架构分析
        // ===================================================================
        Set<String> departments = employeeMap.values().stream()
            .map(Employee::getDepartment)
            .collect(Collectors.toSet());
        System.out.println("\n==== 所有部门 ====\n" + departments);

        // ===================================================================
        // 3. Map键值反转：ID->员工 转换为 员工->ID (collect(Collectors.toMap))
        // 场景：需要反向查找的场景
        // ===================================================================
        Map<Employee, Integer> employeeToIdMap = employeeMap.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getValue,
                Map.Entry::getKey
            ));
        System.out.println("\n==== 员工到ID的映射 ====\n" + employeeToIdMap);

        // ===================================================================
        // 4. Map分组：按部门分组员工 (groupingBy)
        // 场景：部门管理
        // ===================================================================
        Map<String, List<Employee>> employeesByDept = employeeMap.values().stream()
            .collect(Collectors.groupingBy(Employee::getDepartment));
        System.out.println("\n==== 按部门分组 ====");
        employeesByDept.forEach((dept, list) -> 
            System.out.println(dept + ": " + list.size() + " 名员工"));

        // ===================================================================
        // 5. Map过滤键：筛选缺货商品 (keySet().stream().filter())
        // 场景：库存管理系统
        // ===================================================================
        List<String> outOfStockProducts = productStock.entrySet().stream()
            .filter(entry -> entry.getValue() == 0)
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
        System.out.println("\n==== 缺货商品 ====\n" + outOfStockProducts);

        // ===================================================================
        // 6. Map转换值：给所有员工加薪10% (replaceAll)
        // 场景：年度调薪
        // ===================================================================
        employeeMap.replaceAll((id, emp) -> {
            double newSalary = emp.getSalary() * 1.1;
            return new Employee(emp.getName(), emp.getDepartment(), newSalary, emp.getAge());
        });
        System.out.println("\n==== 调薪后员工数据 ====\n" + employeeMap);

        // ===================================================================
        // 7. Map合并：合并两个部门的员工 (flatMap)
        // 场景：组织架构重组
        // ===================================================================
        Map<Integer, Employee> techDept = Map.of(
            201, new Employee("陈工", "技术部", 16000, 30),
            202, new Employee("林工", "技术部", 17000, 33)
        );

        Map<Integer, Employee> mergedMap = Stream.of(employeeMap, techDept)
            .flatMap(map -> map.entrySet().stream())
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (existing, replacement) -> existing // 解决键冲突
            ));
        System.out.println("\n==== 合并后的员工表 ====\n" + mergedMap);

        // ===================================================================
        // 8. Map统计：计算客户总消费金额 (entrySet().stream().mapToDouble)
        // 场景：客户价值分析
        // ===================================================================
        Map<String, Double> customerTotalSpent = customerOrders.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().stream()
                    .mapToDouble(Order::getAmount)
                    .sum()
            ));
        System.out.println("\n==== 客户总消费 ====\n" + customerTotalSpent);

        // ===================================================================
        // 9. Map排序：按薪资排序员工 (sorted + collect)
        // 场景：薪酬报表生成
        // ===================================================================
        LinkedHashMap<Integer, Employee> sortedBySalary = employeeMap.entrySet().stream()
            .sorted(Map.Entry.comparingByValue(
                Comparator.comparingDouble(Employee::getSalary).reversed()
            ))
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (oldVal, newVal) -> oldVal,
                LinkedHashMap::new // 保持排序顺序
            ));
        System.out.println("\n==== 按薪资降序排序 ====");
        sortedBySalary.forEach((id, emp) -> 
            System.out.println(id + ": " + emp.getName() + " - " + emp.getSalary()));

        // ===================================================================
        // 10. Map查找：查找最高薪资员工 (max)
        // 场景：绩效评估
        // ===================================================================
        Optional<Map.Entry<Integer, Employee>> topEarner = employeeMap.entrySet().stream()
            .max(Comparator.comparingDouble(
                entry -> entry.getValue().getSalary()
            ));
        topEarner.ifPresent(entry -> 
            System.out.println("\n==== 最高薪资员工 ====\n" + 
                entry.getKey() + ": " + entry.getValue().getName() + 
                " - " + entry.getValue().getSalary()));

        // ===================================================================
        // 11. Map条件检查：检查所有员工是否都满足最低薪资 (allMatch)
        // 场景：薪酬合规检查
        // ===================================================================
        boolean allAboveMinWage = employeeMap.values().stream()
            .allMatch(emp -> emp.getSalary() >= 8000);
        System.out.println("\n==== 所有员工薪资达标: " + allAboveMinWage + " ====");

        // ===================================================================
        // 12. Map转换：生成员工薪资报告 (map + collect)
        // 场景：薪酬报表
        // ===================================================================
        List<String> salaryReport = employeeMap.entrySet().stream()
            .map(entry -> "ID:" + entry.getKey() + 
                 " | " + entry.getValue().getName() + 
                 " | 薪资:" + entry.getValue().getSalary())
            .collect(Collectors.toList());
        System.out.println("\n==== 薪资报告 ====");
        salaryReport.forEach(System.out::println);

        // ===================================================================
        // 13. Map复杂操作：按部门统计平均薪资 (groupingBy + averagingDouble)
        // 场景：部门绩效分析
        // ===================================================================
        Map<String, Double> avgSalaryByDept = employeeMap.values().stream()
            .collect(Collectors.groupingBy(
                Employee::getDepartment,
                Collectors.averagingDouble(Employee::getSalary)
            ));
        System.out.println("\n==== 部门平均薪资 ====\n" + avgSalaryByDept);
    }

    static class Employee {
        private String name;
        private String department;
        private double salary;
        private int age;
        
        public Employee(String name, String department, double salary, int age) {
            this.name = name;
            this.department = department;
            this.salary = salary;
            this.age = age;
        }
        
        // Getters
        public String getName() { return name; }
        public String getDepartment() { return department; }
        public double getSalary() { return salary; }
        public int getAge() { return age; }
        
        @Override
        public String toString() {
            return name + "(" + department + ":" + salary + ")";
        }
    }

    static class Order {
        private String orderId;
        private double amount;
        
        public Order(String orderId, double amount) {
            this.orderId = orderId;
            this.amount = amount;
        }
        
        public double getAmount() { return amount; }
        
        @Override
        public String toString() {
            return orderId + ":" + amount;
        }
    }
}